package com.sunrise.financeiro.bean;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;

import javax.annotation.Resource;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ComponentSystemEvent;

import lombok.Getter;

import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
import org.springframework.stereotype.Controller;

import br.com.caelum.stella.boleto.Banco;
import br.com.caelum.stella.boleto.Datas;
import br.com.caelum.stella.boleto.Emissor;
import br.com.caelum.stella.boleto.Sacado;
import br.com.caelum.stella.boleto.bancos.Bancos;
import br.com.caelum.stella.boleto.bancos.Itau;
import br.com.caelum.stella.boleto.transformer.GeradorDeBoleto;

import com.sunrise.financeiro.servico.ManterBoletoService;
import com.sunrise.financeiro.visao.BoletoForm;
import com.sunrise.generico.bean.ManterBean;
import com.sunrise.generico.entidade.Boleto;
import com.sunrise.generico.entidade.Cidade;
import com.sunrise.generico.entidade.ContaCedente;
import com.sunrise.generico.entidade.Endereco;
import com.sunrise.generico.entidade.Estado;
import com.sunrise.generico.enums.TipoStatus;
import com.sunrise.generico.util.MessagesUtil;
import com.sunrise.generico.util.WebServiceCep;
import com.sunrise.generico.visao.Filtro;

@ManagedBean
@ViewScoped
@Controller
public class ManterBoletoBean extends ManterBean<Boleto> {

	@Resource
	@Getter
	private ManterBoletoService boletoService;

	@Resource
	@Getter
	private BoletoForm formulario;

	public void preRenderList(ComponentSystemEvent event) {
		setStatus(Arrays.asList(TipoStatus.values()));
		inicializarEntidade();
		setFiltro(new Filtro());
		buscarPorFiltros();
	}

	@Override
	public void inicializarEntidade() {
		setEntidade(new Boleto());
		getEntidade().setCedente(new ContaCedente());
		getEntidade().setEnderecoSacado(new Endereco());
		getEntidade().getEnderecoSacado().setCidade(new Cidade());
		getEntidade().getEnderecoSacado().getCidade().setEstado(new Estado());
		carregarFormulario();
	}

	private void carregarFormulario() {
		getFormulario().setEstados(getBoletoService().listarEstados());
		getFormulario().setContas(getBoletoService().listarContasPorUsuario(obterUsuarioLogado()));

	}

	@Override
	public List<Boleto> iniciarlizarListEntidade() {
		return new ArrayList<Boleto>();
	}

	public Boolean validarBoleto() {
		return false;
	}

	@Override
	public String salvar() {
		try {
			if (validarBoleto()) {
				getService().inserir(getEntidade());
				MessagesUtil.addNewInfoMessage(MessagesUtil.getMessageKey("criadoSucesso"));
				carregarListagem();
				return getListar();
			} else {
				MessagesUtil.addNewInfoMessage(MessagesUtil.getMessageKey("dadosBoletoInvalido"));
				return null;
			}
		} catch (Exception ex) {
			MessagesUtil.addNewInfoMessage(ex.getMessage());

		}
		return null;
	}

	public void buscarPorFiltros() {
		getFiltro().setIdUsuarioLogado(obterUsuarioLogado().getId());
		setEntidades(getBoletoService().buscarPorFiltros(getFiltro()));
	}

	public StreamedContent getGerarBoleto() {
		if (validarDadosBoleto()) {
			getEntidade().setCedente(getBoletoService().buscarConta(getEntidade().getCedente().getId()));
			getEntidade().setNossoNumero(gerarNossoNumero(getEntidade().getCedente()));
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(getEntidade().getDataVencimento());
			Datas datas = Datas.novasDatas().comVencimento(calendar);

			if (getEntidade().getCedente().getCodigoBanco().equals(Bancos.BANCO_DO_BRASIL.getNumeroDoBanco())) {

			} else if (getEntidade().getCedente().getCodigoBanco().equals(Bancos.SANTANDER.getNumeroDoBanco())) {

			} else if (getEntidade().getCedente().getCodigoBanco().equals(Bancos.BRADESCO.getNumeroDoBanco())) {

			} else if (getEntidade().getCedente().getCodigoBanco().equals(Bancos.CAIXA.getNumeroDoBanco())) {

			} else if (getEntidade().getCedente().getCodigoBanco().equals(Bancos.HSBC.getNumeroDoBanco())) {

			} else if (getEntidade().getCedente().getCodigoBanco().equals(Bancos.ITAU.getNumeroDoBanco())) {
				return gerarBoletoItau(datas);
			} else if (getEntidade().getCedente().getCodigoBanco().equals(Bancos.SAFRA.getNumeroDoBanco())) {

			}else {
				MessagesUtil.addNewInfoMessage(MessagesUtil.getMessageKey("codigoBancarioInvalido"));
				return null;
			}
			return null;
		}else{
			MessagesUtil.addNewInfoMessage(MessagesUtil.getMessageKey("dadosBoletoInvalido"));
			return null;
		}

	}

	private boolean validarDadosBoleto() {
		boolean retorno = true;
		if(getEntidade().getCedente().getId() == null || getEntidade().getCedente().getId() == 0){
			retorno = false;
		}
		return retorno;
	}

	public StreamedContent gerarBoleto(br.com.caelum.stella.boleto.Boleto boleto) {
		GeradorDeBoleto gerador = new GeradorDeBoleto(boleto);

		// Para gerar um array de bytes a partir de um PDF
		byte[] bPDF = gerador.geraPDF();

		// byte[] bPNG = gerador.geraPNG();

		InputStream relatorio = new ByteArrayInputStream(bPDF);
		return new DefaultStreamedContent(relatorio, "application/pdf", "teste" + ".pdf");

	}

	public StreamedContent gerarBoletoItau(Datas datas) {
		Emissor emissor = Emissor.novoEmissor().comCedente(getEntidade().getCedente().getNome())
				.comAgencia(getEntidade().getCedente().getAgencia())
				.comContaCorrente(getEntidade().getCedente().getContaCorrente())
				.comDigitoContaCorrente(getEntidade().getCedente().getDvContaCorrente())
				.comCarteira(getEntidade().getCedente().getCarteira()).comNossoNumero(getEntidade().getNossoNumero())
				.comDigitoNossoNumero("1");

		StringBuilder str = new StringBuilder(getEntidade().getEnderecoSacado().getEndereco());
		str.append(" ");
		str.append(getEntidade().getEnderecoSacado().getComplemento());
		str.append(" ");
		str.append(getEntidade().getEnderecoSacado().getNumero());

		Sacado sacado = Sacado.novoSacado().comNome(getEntidade().getNome()).comCpf(getEntidade().getCpf())
				.comEndereco(str.toString()).comBairro(getEntidade().getEnderecoSacado().getBairro())
				.comCep(getEntidade().getEnderecoSacado().getCep());

		sacado.comCidade(getEntidade().getEnderecoSacado().getCidade().getNome()).comUf(
				getEntidade().getEnderecoSacado().getCidade().getEstado().getUf());

		Banco banco = new Itau();

		br.com.caelum.stella.boleto.Boleto boleto = br.com.caelum.stella.boleto.Boleto
				.novoBoleto()
				.comBanco(banco)
				.comDatas(datas)
				.comEmissor(emissor)
				.comSacado(sacado)
				.comValorBoleto(getEntidade().getValor())
				.comNumeroDoDocumento("1234")
				.comInstrucoes(getEntidade().getInstrucoes1(), getEntidade().getInstrucoes2(),
						getEntidade().getInstrucoes3());
		return gerarBoleto(boleto);
	}

	private long gerarNossoNumero(ContaCedente contaCedente) {
		contaCedente.setNossoNumero(getBoletoService().gerarNossoNumero() + 1);
		getBoletoService().alterarContaCedente(contaCedente);
		return contaCedente.getNossoNumero();
	}

	public void consultarCep() {
		if (getEntidade().getEnderecoSacado().getCep() != null && !getEntidade().getEnderecoSacado().getCep().isEmpty()) {
			WebServiceCep cep = WebServiceCep.searchCep(getEntidade().getEnderecoSacado().getCep());
			if (cep != null) {
				getEntidade().getEnderecoSacado().setBairro(cep.getBairro());
				getEntidade().getEnderecoSacado().setEndereco(cep.getLogradouroType() + " " + cep.getLogradouro());
				getEntidade().getEnderecoSacado().setCidade(getBoletoService().buscarCidadePorNome(cep.getCidade()));
			}
			carregarCidades();
		}
	}

	public void carregarCidades() {
		getFormulario().setCidades(
				getBoletoService().carregarCidadesPorEstado(getEntidade().getEnderecoSacado().getCidade().getEstado()));

	}
}
